package com.example.demo.controller;


import com.example.demo.entity.Shift;
import com.example.demo.pojo.*;
import com.example.demo.service.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.util.*;

import static com.example.demo.pojo.Rule.*;

/**
 * @Project:demo
 * @Description:
 * @Author: Mr.Hunter
 * @Date:2023/5/25/17:54
 */
@RestController
@RequestMapping("/Store")
public class StoreController {
    @Autowired
    private StoreService storeService;
    @Autowired
    private StaffService staffService;
    @Autowired
    private PassengerFlowService passengerFlowService;
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private ShiftService shiftService;

    /*
        时间转化函数 将当前日期转化为相对应的常数
        （1-7）星期一到星期日
     */
    private int dateConversionInt(String workDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = null;
        try {
            date = sdf.parse(workDate);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int i = calendar.get(Calendar.DAY_OF_WEEK);
        if (i == 1) return 7;
        else
            return i - 1;
    }

    @ApiOperation("通过店铺ip查询店铺")
    @ResponseBody
    @GetMapping(value = "/selectStoreByStoreID/{store_id}")
    public List<Store> selectStoreByStoreID(@PathVariable("store_id") Integer storeId) {
        return storeService.selectStoreByStoreID(storeId);
    }


    @ApiOperation("店铺id查找排班表")
    @ResponseBody
    @GetMapping(value = "/findAllByStoreIdAndWorkDate/{store_id}/{work_date}")
    public List<Shift> findAllByStoreIdAndWorkDate(@PathVariable("store_id")Integer store_id)  {
        return shiftService.findByStoreId(store_id);
    }




    @ApiOperation("店铺ip和日期查询排班表")
    @ResponseBody
    @GetMapping(value = "/findAllByStoreIdAndWorkDate/{store_id}/{work_date}")
    public List<Shift> findAllByStoreIdAndWorkDate(@PathVariable("store_id")Integer store_id,@PathVariable("work_date")
    @DateTimeFormat(pattern = "yyyy-MM-dd")String date) throws ParseException {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date workDate = format.parse(date);
        java.sql.Date work_date = new java.sql.Date(workDate.getTime());
        return shiftService.findAllByStoreIdAndWorkDate(store_id,work_date);
    }




    @ApiOperation("将当前员工某一区间的班次进行调整,对原来存在的班次进行修改，可以增加班次长度也可缩短-【扩展班次】")
    @ResponseBody
    @GetMapping(value = "/updateRangeStaffSchedulingByBeginAndEnd/{store_id}/{staff_id}/" +
            "{begin_time}/{end_time}/{work_date}/{origin_start_time}/{origin_end_time}")
    public int updateRangeStaffSchedulingByBeginAndEnd(@PathVariable("store_id") Integer storeId
            , @PathVariable("staff_id") Integer staffId, @PathVariable("begin_time") Integer beginTime, @PathVariable("end_time") Integer endTime
            , @PathVariable("work_date") String workDate, @PathVariable("origin_start_time") Integer originStartTime, @PathVariable("origin_end_time") Integer originEndTime) {
        List<Schedule> scheduleList = scheduleService.selectStaffScheduleByStoreIdAndStaffIdAndWorkDate(storeId, staffId, workDate);
        String staffSchedule = scheduleList.get(0).getStaffSchedule();
        int beginIndex = Math.min(beginTime, originStartTime);
        int endIndex = Math.max(originEndTime, endTime);
        StringBuilder builder = new StringBuilder();
        int length = staffSchedule.length();
        for (int i = 0; i < length; i++) {
            if (staffSchedule.charAt(i) == '1' && (i < beginIndex || i > endIndex)) {
                builder.append('1');
            } else if (i >= beginTime && i <= endTime) {
                builder.append('1');
            } else if (i >= beginIndex && i <= beginTime) {
                builder.append('0');
            } else if (i < endIndex && i > endTime) {
                builder.append('0');
            } else {
                builder.append('0');
            }
        }
        return scheduleService.updateStaffScheduleByWorkDateAndStoreId(storeId, staffId, workDate, builder.toString());
    }

    @ApiOperation("通过店铺id和工作日期查询店铺排班表")
    @ResponseBody
    @GetMapping(value = "/selectByStoreIdByWorkDate/{store_id}{work_date}")
    public List<Schedule> selectByStoreIdByWorkDate
            (@PathVariable("store_id") Integer storeId, @PathVariable("work_date") String workDate) {
        List<Schedule> scheduleList = scheduleService.selectStaffScheduleByStoreIdAndWorkDate(storeId, workDate);
        return scheduleList;
    }


    @ApiOperation("通过店铺id，员工id和工作日期查询员工排班表")
    @ResponseBody
    @GetMapping(value = "/selectStaffScheduleByStoreIdAndStaffIdAndWorkDate/{store_id}/{staff_id}/{work_date}")
    public List<Schedule> selectStaffScheduleByStoreIdAndStaffIdAndWorkDate
            (@PathVariable("store_id") Integer storeId, @PathVariable("staff_id") Integer staff_id, @PathVariable("work_date") String workDate) {
        List<Schedule> scheduleList = scheduleService.selectStaffScheduleByStoreIdAndStaffIdAndWorkDate(storeId, staff_id, workDate);
        return scheduleList;
    }


    /*
        需要
        初始化store
    */
    @ApiOperation("【🐏】第一次加载使用这个,通过店铺id进行自动排班生成，workDate的格式为yyyyMMdd")
    @ResponseBody
    @GetMapping(value = "/useGA/{storeId}/{workDate}")
    public void useGA(@PathVariable("storeId") int storeId, @PathVariable("workDate") String workDate) {//需要把客流预测也输入给Store
        //初始化商铺
        List<Store> list = storeService.selectStoreByStoreID(storeId);
        Store store = list.get(0);
        String name = store.getName();
        String address = store.getAddress();
        float size = store.getSize();
        //获得当前店铺员工数据集
        List<Staff> staffList = staffService.selectStaffAllByStore(storeId);
        HashMap<String, Staff> staffMap = new HashMap<>();
        for (int i = 0; i < staffList.size(); i++) {
            staffMap.put(staffList.get(i).getName(), staffList.get(i));
        }
        store = new Store(name, address, size, staffMap);
        //员工Gene初始化
        int pre = (int) (PRE_WORK_TIME / 0.5);
        int later = (int) (AFT_WORK_TIME / 0.5);
        int len = pre + later + 24;


        for (Staff stu : staffMap.values()) {
            Staff tmp = new Staff();
            tmp = stu;
            tmp.gene.len = len;
            staffMap.replace(stu.getName(), tmp);
        }//设置长度
        for (Staff stu : staffMap.values()) {
            Staff tmp = new Staff();
            tmp = stu;
            Gene gene = new Gene();
            tmp.gene = gene;
            staffMap.replace(stu.getName(), tmp);
        }


        //客流模型初始化
        ArrayList<Double> passengerFlow = new ArrayList<>();
        List<PassengerFlow> passengerFlowList = passengerFlowService.selectAllByDateAndShopID(workDate, storeId);
        //使用数据库拿到客流量数据


        //客流量数据
        //这里需要根据时间改变 然后改变客流数据

        for (int i = 0; i < passengerFlowList.size(); i++) {
            String customers = passengerFlowList.get(i).getForecast();
            passengerFlow.add(Double.valueOf(customers) / PASSENGER_FLOW_NEED);
        }

        //计算需要人数
        int preNum = (int) Math.abs((size / STORE_SIZE_NEED_BEFORE));
        int freeNum = (int) (FREE_POPULATION);
        int afterNum = ((int) (size / STORE_SIZE_NEED_AFTER_1) + STORE_SIZE_NEED_AFTER_2) + 1;

        GAGroup gaGroup = store.getGAGroup();
        ArrayList<Gene> group = store.getGroup();
        //开始公式计算并传参进行GA,完成排班
        //这里的workDate(Date)转化day(int)

        int Day = dateConversionInt(workDate);
        group = gaGroup.GA(preNum, freeNum, afterNum, passengerFlow, pre, later, Day);

        for (int i = 0; i < group.size(); i++) {
//            Date workingDate = stringConversionDate(workDate);
            StringBuilder builder = new StringBuilder();
            ArrayList<Integer> geneList = group.get(i).geneList;
            if (geneList.get(0) == 1) builder.append(1);
            else builder.append(0);
            for (int j = 0; j < geneList.size(); j++) {
                builder.append(geneList.get(j));
            }
            /*
            i+1是员工ID
            因为数据没写员工ID信息
             */
            scheduleService.insertScheduleByWorkDateAndStoreId(storeId, staffList.get(i).getStaffId(), workDate, builder.toString());
        }
    }


    @ApiOperation("【🐏】更新使用这个,通过店铺id进行自动排班生成，workDate的格式为yyyyMMdd")
    @ResponseBody
    @GetMapping(value = "/updateGA/{storeId}/{workDate}")
    public void updateGA(@PathVariable("storeId") int storeId, @PathVariable("workDate") String workDate) {//需要把客流预测也输入给Store
        //初始化商铺
        List<Store> list = storeService.selectStoreByStoreID(storeId);
        Store store = list.get(0);
        String name = store.getName();
        String address = store.getAddress();
        float size = store.getSize();
        //获得当前店铺员工数据集
        List<Staff> staffList = staffService.selectStaffAllByStore(storeId);
        HashMap<String, Staff> staffMap = new HashMap<>();
        for (int i = 0; i < staffList.size(); i++) {
            staffMap.put(staffList.get(i).getName(), staffList.get(i));
        }
        store = new Store(name, address, size, staffMap);
        //员工Gene初始化
        int pre = (int) (PRE_WORK_TIME / 0.5);
        int later = (int) (AFT_WORK_TIME / 0.5);
        int len = pre + later + 24;


        for (Staff stu : staffMap.values()) {
            Staff tmp = new Staff();
            tmp = stu;
            tmp.gene.len = len;
            staffMap.replace(stu.getName(), tmp);
        }//设置长度
        for (Staff stu : staffMap.values()) {
            Staff tmp = new Staff();
            tmp = stu;
            Gene gene = new Gene();
            tmp.gene = gene;
            staffMap.replace(stu.getName(), tmp);
        }


        //客流模型初始化
        ArrayList<Double> passengerFlow = new ArrayList<>();
        List<PassengerFlow> passengerFlowList = passengerFlowService.selectAllByDateAndShopID(workDate, storeId);
        //使用数据库拿到客流量数据


        //客流量数据
        //这里需要根据时间改变 然后改变客流数据

        for (int i = 0; i < passengerFlowList.size(); i++) {
            String customers = passengerFlowList.get(i).getForecast();
            passengerFlow.add(Double.valueOf(customers) / PASSENGER_FLOW_NEED);
        }

        //计算需要人数
        int preNum = (int) Math.abs((size / STORE_SIZE_NEED_BEFORE));
        int freeNum = (int) (FREE_POPULATION);
        int afterNum = ((int) (size / STORE_SIZE_NEED_AFTER_1) + STORE_SIZE_NEED_AFTER_2) + 1;

        GAGroup gaGroup = store.getGAGroup();
        ArrayList<Gene> group = store.getGroup();
        //开始公式计算并传参进行GA,完成排班
        //这里的workDate(Date)转化day(int)

        int Day = dateConversionInt(workDate);
        group = gaGroup.GA(preNum, freeNum, afterNum, passengerFlow, pre, later, Day);

        for (int i = 0; i < group.size(); i++) {
//            Date workingDate = stringConversionDate(workDate);
            StringBuilder builder = new StringBuilder();
            ArrayList<Integer> geneList = group.get(i).geneList;
            if (geneList.get(0) == 1) builder.append(1);
            else builder.append(0);
            for (int j = 0; j < geneList.size(); j++) {
                builder.append(geneList.get(j));
            }
            /*
            i+1是员工ID
            因为数据没写员工ID信息
             */
            scheduleService.updateStaffScheduleByWorkDateAndStoreId(storeId, staffList.get(i).getStaffId(), workDate, builder.toString());
        }
    }

    @ApiOperation("员工请假全天")
    @ResponseBody
    @GetMapping(value = "/RestStaffScheduling/{store_id}/{staff_id}/{work_date}")
    public int RestAllDayStaffScheduling(@PathVariable("store_id") Integer storeId, @PathVariable("staff_id") Integer staffId, @PathVariable("work_date") String workDate) {
        int len = 29;
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < len; i++) {
            builder.append('0');
        }
        return scheduleService.updateStaffScheduleByWorkDateAndStoreId(storeId, staffId, workDate, builder.toString());
    }

    @ApiOperation("员工请假某一时间段，start_time作为请假时间开始下标，end_time作为请假时间结束下标范围为【0，28】,时间格式使用yyyyMMdd")
    @ResponseBody
    @GetMapping(value = "/restStaffScheduling/{store_id}/{staff_id}/{work_date}/{start_time}/{end_time}")
    public int restRangeStaffScheduling(@PathVariable("store_id") Integer storeId, @PathVariable("staff_id")
    Integer staffId, @PathVariable("work_date") String workDate, @PathVariable("start_time") Integer start_time,
                                        @PathVariable("end_time") Integer end_time) {
        StringBuilder builder = new StringBuilder();
        List<Schedule> scheduleList = scheduleService.selectStaffScheduleByStoreIdAndStaffIdAndWorkDate(storeId, staffId, workDate);
        String staffSchedule = scheduleList.get(0).getStaffSchedule();
        for (int i = 0; i < staffSchedule.length(); i++) {
            if (i >= start_time && i <= end_time) {
                builder.append('0');
            } else {
                builder.append(staffSchedule.charAt(i));
            }
        }
        return scheduleService.updateStaffScheduleByWorkDateAndStoreId(storeId, staffId, workDate, builder.toString());
    }


    @ApiOperation("保持当前员工班别不动的前提下,进行当前员工的班次的增加（开始和结束时间）-抢班")
    @ResponseBody
    @GetMapping(value = "/SnatchRangeStaffScheduling/{store_id}/{staff_id}/{work_date}/{start_time}/{end_time}")
    public int SnatchRangeStaffScheduling(@PathVariable("store_id") Integer storeId, @PathVariable("staff_id")
    Integer staffId, @PathVariable("work_date") String workDate, @PathVariable("start_time") Integer start_time,
                                          @PathVariable("end_time") Integer end_time) {
        StringBuilder builder = new StringBuilder();
        List<Schedule> scheduleList = scheduleService.selectStaffScheduleByStoreIdAndStaffIdAndWorkDate(storeId, staffId, workDate);
        String staffSchedule = scheduleList.get(0).getStaffSchedule();
        for (int i = 0; i < staffSchedule.length(); i++) {
            if (i >= start_time && i <= end_time) {
                builder.append('1');
            } else {
                builder.append(staffSchedule.charAt(i));
            }
        }
        return scheduleService.updateStaffScheduleByWorkDateAndStoreId(storeId, staffId, workDate, builder.toString());
    }

    @ApiOperation("将当前员工当天班次置空，再进行当前员工的班次的增加（开始和结束时间），时间格式yyyyMMdd-(重新排班)")
    @ResponseBody
    @GetMapping(value = "/updateEmptyStaffSchedulingByBeginAndEnd/{store_id}/{staff_id}/{work_date}/{start_time}/{end_time}")
    public int updateEmptyStaffSchedulingByBeginAndEnd(@PathVariable("store_id") Integer storeId, @PathVariable("staff_id")
    Integer staffId, @PathVariable("work_date") String workDate, @PathVariable("start_time") Integer start_time,
                                                       @PathVariable("end_time") Integer end_time) {
        StringBuilder builder = new StringBuilder();
        int len = 29;
        for (int i = 0; i < len; i++) {
            if (i >= start_time && i <= end_time) {
                builder.append('1');
            } else {
                builder.append('0');
            }
        }
        return scheduleService.updateStaffScheduleByWorkDateAndStoreId(storeId, staffId, workDate, builder.toString());
    }


}